---
slug: minimal-api
title: Minimal API
description: The minimal Waku API for library authors.
---

## Minimal

### Server API

To use React Server Components in Waku, you need to create an `server-entry.tsx` file in the project root directory and `defineHandlers` to handle server requests.

```tsx
import { unstable_defineHandlers as defineHandlers } from 'waku/minimal/server';
import adapter from 'waku/adapters/default';
import App from './components/App.js';

const handlers = defineHandlers({
  handleRequest: async (input, { renderRsc, renderHtml }) => {
    if (input.type === 'component') {
      return renderRsc({ App: <App name={input.rscPath || 'Waku'} /> });
    }
    if (input.type === 'custom' && input.pathname === '/') {
      return renderHtml(
        await renderRsc({ App: <App name="Waku" /> }),
        <Slot id="App" />,
        '',
      );
    }
  },
  handleBuild: () => null,
});

export default adapter(handlers);
```

Tips for experimenting:

- Object keys like `App` are called RSC ID.
- `input.type === 'custom'` condition can be omitted if you don't need SSR.

#### `handleBuild`

The `handleBuild` function is to produce a build for production.
It has to return AsyncIterable of build instructions.

```tsx
  handleBuild: ({
    renderRsc,
    renderHtml,
    rscPath2pathname,
  }) =>
    createAsyncIterable(async () => {
      const tasks = [
        async () => ({
          type: 'file' as const,
          pathname: rscPath2pathname(''),
          body: renderRsc({ App: <App name="Waku" /> }),
        }),
        async () => ({
          type: 'file' as const,
          pathname: '/',
          body: renderHtml(
            await renderRsc({ App: <App name="Waku" /> }),
            <Slot id="App" />,
            {
              rscPath: '',
            },
          ).then((res) => res.body || ''),
        }),
      ];
      return tasks;
    }),
```

### Client API

To render a React Server Component on the client, you can use the `Root` and `Slot` components from `waku/client` with the RSC ID to create a wrapper component.

This file should be `./src/client-entry.tsx`.

```tsx
import { createRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/minimal/client';

const rootElement = (
  <StrictMode>
    <Root>
      <Slot id="App" />
    </Root>
  </StrictMode>
);

createRoot(document.getElementById('root')!).render(rootElement);
```

The `initialRscPath` prop can be passed to the `Root` Component, overriding the default rscPath which is `""`. You can also re-render a React Server Component with new rscPath.

```tsx
import { useRefetch } from 'waku/client';

const Component = () => {
  const refetch = useRefetch();
  const handleClick = () => {
    refetch('...');
  };
  // ...
};
```

### Examples

- [../examples/31_minimal](Minimal example)
- [../examples/34_functions](With server functions)
- [../examples/39_api](With custom API endpoints)
- [../examples/51_spa](Fully client components)
